package com.yunxi.service.dubboService.impl.sto;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.yunxi.core.util.BeanTools;
import com.yunxi.core.web.DictConstant;
import com.yunxi.model.order.PmsVehicleStock;
import com.yunxi.model.sto.StoRepairOrder;
import com.yunxi.model.sto.VehicleOffline;
import com.yunxi.service.localService.CodeCreateService;
import com.yunxi.service.localService.sat.SatCustomerFollowService;
import com.yunxi.service.localService.sto.StoRepairOrderService;
import com.yunxi.service.localService.sto.VehicleOfflineService;
import com.yunxi.service.localService.sto.VehicleStockMService;
import com.yunxi.sto.pojo.*;
import com.yunxi.sto.service.StoRepairOrderDubboService;
import com.yunxi.sto.service.StoStockInPlanDubboService;
import com.yunxi.sto.service.StoStockOutPlanDubboService;
import com.yunxi.sto.service.VehicleStockDubboService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 车辆维修单 服务实现类
 * </p>
 *
 * @author caoYong
 * @since 2019-06-04
 */
public class StoRepairOrderDubboServiceImpl implements StoRepairOrderDubboService {

    @Autowired
    @Qualifier(value = "stoRepairOrderServiceImpl")
    StoRepairOrderService stoRepairOrderService;

    @Autowired
    @Qualifier(value = "codeCreateServiceImpl")
    CodeCreateService codeCreateService;

    @Autowired
    @Qualifier(value = "stoStockOutPlanDubboServiceImpl")
    StoStockOutPlanDubboService stoStockOutPlanDubboService;

    @Autowired
    @Qualifier(value = "stoStockInPlanDubboServiceImpl")
    StoStockInPlanDubboService stoStockInPlanDubboService;

    @Autowired
    @Qualifier(value = "vehicleStockDubboServiceImpl")
    VehicleStockDubboService vehicleStockDubboService;

    @Autowired
    @Qualifier(value = "vehicleStockMServiceImpl")
    VehicleStockMService vehicleStockMService;

    @Autowired
    @Qualifier(value = "satCustomerFollowServiceImpl")
    SatCustomerFollowService satCustomerFollowService;

    @Autowired
    @Qualifier(value = "vehicleOfflineServiceImpl")
    VehicleOfflineService vehicleOfflineService;


    @Override
    public StoRepairOrderVO getById(String id) {
        StoRepairOrder stoRepairOrder = stoRepairOrderService.getById(id);
        StoRepairOrderVO stoRepairOrderVO = new StoRepairOrderVO();
        BeanTools.copyProperties(stoRepairOrderVO,stoRepairOrder);
        return stoRepairOrderVO;
    }

    /**
     * 维修单维护
     * @param stoRepairOrderVO
     * @throws Exception
     */
    @Override
    public void saveOrUpdate(StoRepairOrderVO stoRepairOrderVO) throws Exception {
        String vin = stoRepairOrderVO.getVin();
        String oldVin = null;
        if(StringUtils.isEmpty(vin))throw new Exception("操作失败,VIN码不能为空!");
        stoRepairOrderVO.setVin(vin.replaceAll("\\s+",""));//去空格

        StoRepairOrder stoRepairOrder = new StoRepairOrder();
        BeanTools.copyProperties(stoRepairOrder,stoRepairOrderVO);
        QueryWrapper<StoRepairOrder> queryWrapper = new QueryWrapper();
        if(stoRepairOrder.getRepairOrderId() == null){
            String repairOrderNo = codeCreateService.createCode("SRO", 4);
            stoRepairOrder.setRepairOrderNo(repairOrderNo);
            stoRepairOrder.setOrderState("1");//新建
        }
        else {
            StoRepairOrder stoRepairOrder1 = stoRepairOrderService.getById(stoRepairOrder.getRepairOrderId());
            if(stoRepairOrder1 != null){
                oldVin = stoRepairOrder1.getVin();
            }
            //只能编辑新建的单据
            String orderState = stoRepairOrderVO.getOrderState();
            if(orderState != null && !orderState.equals(1)){
                throw new Exception("操作失败,只能编辑新建的单据!");
            }
            queryWrapper.ne("REPAIR_ORDER_ID",stoRepairOrder.getRepairOrderId());
        }
        //校验一个VIN码不能存在多条未维修完成/未作废的维修单
        queryWrapper.eq("VIN",stoRepairOrderVO.getVin());
        queryWrapper.ne("ORDER_STATE","4");
        queryWrapper.ne("ORDER_STATE","5");
        List<StoRepairOrder> list = stoRepairOrderService.list(queryWrapper);
        if(list != null && list.size() > 0){
            throw new Exception("操作失败,车辆VIN码:"+stoRepairOrderVO.getVin()+"已存在未完成或未作废的维修单!");
        }
        stoRepairOrderService.saveOrUpdate(stoRepairOrder);
        //冻结所选VIN,解冻旧VIN
        if(oldVin == null){
            frozenVin(vin,1);
        }
        else if(oldVin != null && !oldVin.equals(vin)){
            frozenVin(vin,1);
            frozenVin(oldVin,0);
        }
    }

    /**
     * 冻结/解冻车辆
     * @param vin
     * @param isFrozen
     */
    private void frozenVin(String vin,Integer isFrozen) {
        QueryWrapper<PmsVehicleStock> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("VIN", vin);
        PmsVehicleStock pmsVehicleStock = vehicleStockMService.getOne(queryWrapper1);
        if (pmsVehicleStock != null) {
            pmsVehicleStock.setVehicleIsFrozen(isFrozen.toString());
            vehicleStockMService.saveOrUpdate(pmsVehicleStock);
        }
        QueryWrapper<VehicleOffline> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("VIN", vin);
        VehicleOffline vehicleOffline = vehicleOfflineService.getOne(queryWrapper2);
        if (vehicleOffline != null) {
            vehicleOffline.setVehicleIsFrozen(isFrozen);
            vehicleOfflineService.saveOrUpdate(vehicleOffline);
        }
        //新增冻结历史
        VehicleStockFrozenVO vehicleStockFrozenVO = new VehicleStockFrozenVO();
        vehicleStockFrozenVO.setFrozenReason("车辆维修");
        vehicleStockMService.newFrozenHis(isFrozen.toString(),vehicleStockFrozenVO,vin,2);
    }

    @Override
    public void removeById(String id) {
        stoRepairOrderService.removeById(id);
    }

    @Override
    public PageInfo<StoRepairOrderVO> findPageByVO(StoRepairOrderVO stoRepairOrderVO, Integer pageNum, Integer pageSize) {
        PageInfo<StoRepairOrderVO> pageInfo = stoRepairOrderService.pageByVo(stoRepairOrderVO, pageNum, pageSize);
        return pageInfo;
    }

    @Override
    public List<StoRepairOrderExportVO> export(StoRepairOrderVO stoRepairOrderVO) throws Exception {
        List<StoRepairOrderExportVO> list = stoRepairOrderService.export(stoRepairOrderVO);
        //转换字典为中文
        if(list != null && list.size() > 0){
            for (StoRepairOrderExportVO vo : list){
                String repairReason = vo.getRepairReason();//维修原因
                String repairType = vo.getRepairType();//维修类型
                String storageStatus = vo.getStorageStatus();//库存状态
                vo.setRepairReason(satCustomerFollowService.queryDictCn(DictConstant.REPAIR_REASON_KEY,repairReason));
                vo.setRepairType(satCustomerFollowService.queryDictCn(DictConstant.REPAIR_TYPE_KEY,repairType));
                vo.setStorageStatus(satCustomerFollowService.queryDictCn(DictConstant.STORAGE_STATUS_KEY,storageStatus));
            }
        }
        return list;
    }

    /**
     * 导入新增维修单
     * @param list
     * @throws Exception
     */
    @Override
    public void importBatch(List<StoRepairOrderImpotVO> list) throws Exception {
        if(list == null || list.size() <= 0)throw new Exception("操作失败,导入内容为空!");
        for (StoRepairOrderImpotVO vo : list){
            //1.检查VIN码是否存在
            checkVinIsExist(vo);
            //2.校验一个VIN码只能存在一条未完成的维修单
            checkRepairOrderOnly(vo);
            //3.校验维修原因,转换为字典key
            String repairReason = checkRepairReason(vo);
            //4.校验维修类型,转换为字典key
            String repairType = checkRepairType(vo);
            StoRepairOrder stoRepairOrder = new StoRepairOrder();
            stoRepairOrder.setVin(vo.getVin());
            String repairOrderNo = codeCreateService.createCode("SRO", 4);
            stoRepairOrder.setRepairOrderNo(repairOrderNo);
            stoRepairOrder.setOrderState("1");
            stoRepairOrder.setRepairReason(repairReason);
            stoRepairOrder.setRepairType(repairType);
            String planCompleteTime = vo.getPlanCompleteTime();
            if(planCompleteTime != null){
                try {
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                    Date parse = simpleDateFormat.parse(planCompleteTime);
                    stoRepairOrder.setPlanCompleteTime(parse);
                }
                catch (ParseException e){
                    throw new Exception("操作失败,预计完成时间:planCompleteTime格式异常!");
                }
            }

            stoRepairOrderService.saveOrUpdate(stoRepairOrder);
        }
    }

    /**
     * 校验维修类型,转换为字典key
     * @param vo
     * @throws Exception
     */
    private String checkRepairType(StoRepairOrderImpotVO vo) throws Exception {
        String repairType = vo.getRepairTypeCn().replaceAll("\\s+", "");
        switch (repairType){
            case DictConstant.CN_REPAIR_TYPE_XCWX:
                repairType = "1";
                break;
            case DictConstant.CN_REPAIR_TYPE_FCWX:
                repairType = "2";
                break;
            case DictConstant.CN_REPAIR_TYPE_CCWX:
                repairType = "3";
                break;
            default:
                throw new Exception("操作失败,维修类型值:"+repairType+"异常!");
        }
        return repairType;
    }

    /**
     * 校验维修原因,转换为字典key
     * @param vo
     * @return
     * @throws Exception
     */
    private String checkRepairReason(StoRepairOrderImpotVO vo) throws Exception {
        String repairReasonCn = vo.getRepairReasonCn().replaceAll("\\s+","");
        switch (repairReasonCn){
            case DictConstant.CN_REPAIR_REASON_YCCL:
                repairReasonCn = "1";
                break;
            case DictConstant.CN_REPAIR_REASON_CLSJ:
                repairReasonCn = "2";
                break;
            case DictConstant.CN_REPAIR_REASON_GHLJ:
                repairReasonCn = "3";
                break;
            default:
                throw new Exception("操作失败,维修原因值:"+repairReasonCn+"异常!");
        }
        return repairReasonCn;
    }


    @Override
    public void removeByListVo(List<StoRepairOrderVO> stoRepairOrderVOList) throws IllegalAccessException, InvocationTargetException, InstantiationException {
        stoRepairOrderService.removeByListVo(stoRepairOrderVOList);
    }

    /**
     * 作废/恢复
     * @param list
     * @param isDel
     */
    @Override
    public void delAndReset(List<String> list, Integer isDel,String userId) throws Exception {
        if(list != null && list.size() > 0){
            for (String id : list){
                StoRepairOrder stoRepairOrder = stoRepairOrderService.getById(id);
                if(stoRepairOrder != null){
                    String orderState = stoRepairOrder.getOrderState();
                    //作废
                    if(isDel == 1){
                        if(orderState != null && !orderState.equals("1")){
                            throw new Exception("操作失败,只能作废新建的单据!");
                        }
                        stoRepairOrder.setOrderState("5");
                    }
                    //恢复
                    else if(isDel == 0){
                        if(orderState != null && !orderState.equals("5")){
                            throw new Exception("操作失败,只能恢复作废的单据!");
                        }
                        //校验该VIN码是否存在未完成的单据,有则不可恢复
                        String vin = stoRepairOrder.getVin();
                        QueryWrapper<StoRepairOrder> queryWrapper = new QueryWrapper();
                        queryWrapper.eq("VIN",vin);
                        queryWrapper.ne("ORDER_STATE","4");
                        queryWrapper.ne("ORDER_STATE","5");
                        queryWrapper.ne("REPAIR_ORDER_ID",stoRepairOrder.getRepairOrderId());
                        List<StoRepairOrder> list1 = stoRepairOrderService.list(queryWrapper);
                        if(list1 != null && list1.size() > 0){
                            throw new Exception("操作失败,车辆VIN码:"+vin+"已存在正在进行中的维修单,不可恢复该条!");
                        }
                        stoRepairOrder.setOrderState("1");
                    }
                    stoRepairOrder.setUpdateBy(userId);
                    stoRepairOrderService.updateById(stoRepairOrder);
                }
                else {
                    throw new Exception("操作失败,无法通过主键id:"+id+"找到对应维修单!");
                }
            }
        }
        else {
            throw new Exception("操作失败,list为空!");
        }
    }

    /**
     * 批量转出入库计划
     * @param list
     * @param isOut
     * @throws Exception
     */
    @Override
    public void batchStockInOut(List<String> list, Integer isOut,String userId) throws Exception {
        if(list != null && list.size() > 0){
            for(String id : list){
                StoRepairOrder stoRepairOrder = stoRepairOrderService.getById(id);
                if(stoRepairOrder != null){
                    //只有新建的单据,并且维修类型为出厂维修才能转出库计划,返厂维修只能转入库计划
                    String orderState = stoRepairOrder.getOrderState();
                    String repairType = stoRepairOrder.getRepairType();
                    String vin = stoRepairOrder.getVin();
                    if(orderState != null && !orderState.equals("1")){
                        throw new Exception("操作失败,只有新建的维修单才能转出入库计划!");
                    }
                    //转出库
                    if(isOut == 1){
                        if(repairType != null && !repairType.equals("3")){
                            throw new Exception("操作失败,只有出厂维修的单据才能转出库计划!");
                        }
                        StoStockOutPlanVO stoStockOutPlanVO = new StoStockOutPlanVO();
                        stoStockOutPlanVO.setVin(vin);
                        stoStockOutPlanVO.setStockOutType("12");//送修出库
                        stoStockOutPlanVO.setRepairOrderNo(stoRepairOrder.getRepairOrderNo());
                        stoStockOutPlanDubboService.saveOrUpdate(stoStockOutPlanVO);
                        stoRepairOrder.setOrderState("2");//已转出库计划
                    }
                    //转入库
                    else if(isOut == 0){
                        if(repairType != null && !repairType.equals("2")){
                            throw new Exception("操作失败,只有返厂维修的单据才能转入库计划!");
                        }
                        StoStockInPlanVO stoStockInPlanVO = new StoStockInPlanVO();
                        stoStockInPlanVO.setVin(vin);
                        stoStockInPlanVO.setStockInType("4");//送修入库
                        Date date = new Date();
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                        stoStockInPlanVO.setPlanStockInDate(simpleDateFormat.format(date));
                        stoStockInPlanVO.setRepairOrderNo(stoRepairOrder.getRepairOrderNo());
                        stoStockInPlanDubboService.saveAndUpdate(stoStockInPlanVO);
                        stoRepairOrder.setOrderState("3");//已转入库计划
                    }
                    stoRepairOrder.setUpdateBy(userId);
                    stoRepairOrderService.updateById(stoRepairOrder);//更改维修单状态
                    //冻结车辆
                    QueryWrapper<PmsVehicleStock> queryWrapper = new QueryWrapper();
                    queryWrapper.eq("VIN",vin);
                    PmsVehicleStock pmsVehicleStock = vehicleStockMService.getOne(queryWrapper);
                    if(pmsVehicleStock != null){
                        List<VehicleStockFrozenVO> arrayList = new ArrayList();
                        VehicleStockFrozenVO vehicleStockFrozenVO = new VehicleStockFrozenVO();
                        vehicleStockFrozenVO.setBusinessKey(pmsVehicleStock.getVehicleId());
                        vehicleStockFrozenVO.setFrozenReason("车辆维修");
                        arrayList.add(vehicleStockFrozenVO);
                        if(isOut == 1){
                            vehicleStockDubboService.frozenAndReset(arrayList,"1",4,userId);
                        }
                        else if (isOut == 0){
                            vehicleStockDubboService.frozenAndReset(arrayList,"1",3,userId);
                        }
                    }
                }
                else{
                    throw new Exception("操作失败,无法根据主键id:"+id+"找到对应维修单!");
                }
            }
        }
        else {
            throw new Exception("操作失败,list为空!");
        }
    }

    /**
     * 批量维修完成
     * @param list
     * @throws Exception
     */
    @Override
    public void batchComplete(List<String> list,String userId) throws Exception {
        if(list != null && list.size() > 0){
            for(String id : list){
                StoRepairOrder stoRepairOrder = stoRepairOrderService.getById(id);
                if(stoRepairOrder != null){
                    //已完成,已作废的单据不可再次完成
                    String orderState = stoRepairOrder.getOrderState();
                    String vin = stoRepairOrder.getVin();
                    if(orderState.equals("4") || orderState.equals("5")){
                        throw new Exception("操作失败,已完成,已作废的单据不可再次完成!");
                    }
                    stoRepairOrder.setOrderState("4");
                    stoRepairOrder.setCompleteTime(new Date());
                    stoRepairOrder.setUpdateBy(userId);
                    stoRepairOrderService.updateById(stoRepairOrder);

                    //解冻车辆
                    unFrozenVehicle(vin,userId);
                }
                else{
                    throw new Exception("操作失败,无法根据主键id:找到对应维修单!");
                }
            }
        }
        else{
            throw new Exception("操作失败,list为空!");
        }
    }

    /**
     * 解冻车辆
     * @param vin
     */
    private void unFrozenVehicle(String vin,String userId) throws Exception{
        QueryWrapper<PmsVehicleStock> queryWrapper = new QueryWrapper();
        queryWrapper.eq("VIN",vin);
        PmsVehicleStock pmsVehicleStock = vehicleStockMService.getOne(queryWrapper);
        if(pmsVehicleStock != null){
            List<VehicleStockFrozenVO> arrayList = new ArrayList();
            VehicleStockFrozenVO vehicleStockFrozenVO = new VehicleStockFrozenVO();
            vehicleStockFrozenVO.setBusinessKey(pmsVehicleStock.getVehicleId());
            arrayList.add(vehicleStockFrozenVO);
            vehicleStockDubboService.frozenAndReset(arrayList,"0",null,userId);
        }
    }

    /**
     * 检查VIN码是否存在
     * @param vo
     * @throws Exception
     */
    private void checkVinIsExist(StoRepairOrderImpotVO vo) throws Exception {
        QueryWrapper<PmsVehicleStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("VIN", vo.getVin());
        PmsVehicleStock vehicleStock = vehicleStockMService.getOne(queryWrapper);
        if(vehicleStock == null) throw new Exception("操作失败,VIN码:"+vo.getVin()+"不存在!");
    }

    /**
     * 校验一个VIN码只能存在一条未完成的维修单
     * @param vo
     * @throws Exception
     */
    private void checkRepairOrderOnly(StoRepairOrderImpotVO vo) throws Exception {
        QueryWrapper<StoRepairOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("VIN",vo.getVin());
        queryWrapper.ne("ORDER_STATE","4");
        queryWrapper.ne("ORDER_STATE","5");
        List<StoRepairOrder> list1 = stoRepairOrderService.list(queryWrapper);
        if(list1 != null && list1.size() > 0) throw new Exception("操作失败,VIN码:"+vo.getVin()+"已存在未完成的维修计划!");
    }
}
